package 注解;
/*
@Inherited注解标记其他的注解用于指明标记的注解是可以被自动继承的。

注意：此注解只对注解标记的超类有效，对接口是无效的。换言之：不能获得所继承接口的注解标识

示例：

先声明两个用@Inherited标记的注解，@Name和@Abbreviation，一个没有用@Inherited标记的注解@UpperCaseName

*/
import java.lang.annotation.*;
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Name {
    //名称
    String value();
}

@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface Abbreviation {
    //简称
    String value();
}

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@interface UpperCaseName {//不可被继承
    //大写英文名称
    String value();
}
//接下来，我们声明一些接口和类用于举例，这些类的继承关系如下：

@UpperCaseName("ORGANISM")
@Abbreviation("Ogm")
@Name("Organism")
interface Organism { }
interface Plant extends Organism{ }//Plant继承了接口Organism,但不能获得Organism接口上的注解

@UpperCaseName("FLOWER")
@Abbreviation("Flr")
@Name("Flower")
abstract class Flower implements Plant { }
class Rose extends Flower { }//Rose继承了Flower抽象类,只要Flower的注解标明@Inherited就能被Rose得到。

@UpperCaseName("ANIMAL")
@Abbreviation("Ani")
@Name("Animal")
interface Animal extends Organism{ }
abstract class Mammal implements Animal { }//Mammal实现Animal接口，但不能获得Animal接口上的注解

@UpperCaseName("MONKEY")
@Abbreviation("Mky")
@Name("Monkey")
class Monkey extends Mammal{ }

@Name("Roxellanae")
class Roxellanae extends Monkey { }//Roxellanae继承了Monkey类，在Monkey类上标记的注解，如果注解是被@Inherited标记的，都可以获取到；
//以下我们创建一个测试类：

public class Inherited使用 {

    public static void main(String[] args){

        Annotation[] annotations = Plant.class.getAnnotations();
        System.out.print("Plant接口继承Organism接口，在Organism接口上标记的注解，Plant获取不到：");
        for (Annotation annotation : annotations){
            System.out.print(annotation.toString()+" ");
        }
        annotations = Mammal.class.getAnnotations();
        System.out.print("\nMamanl抽象类实现Animal接口，在Animal接口上标记的注解，Mammal获取不到：");
        for (Annotation annotation : annotations){
            System.out.print(annotation.toString()+" ");
        }
        annotations = Rose.class.getAnnotations();
        System.out.print("\nRose类继承Flower抽象类，在Flower抽象类上标记的注解，如果注解是被@Inherited标记的，都可以获取到：");
        for (Annotation annotation : annotations){
            System.out.print(annotation.toString()+" ");
        }
        annotations = Roxellanae.class.getAnnotations();
        System.out.print("\nRoxellanae类继承Monkey类，在Monkey抽象类上标记的注解，如果注解是被@Inherited标记的，都可以获取到；"
        		+ "如果被@Inherited标记的注解父类和子类重复标记，则返回子类的注解：");
        for (Annotation annotation : annotations){
            System.out.print(annotation.toString()+" ");
        }
    }
}
/*
输出结果：

Plant接口继承Organism接口，在Organism接口上标记的注解，Plant获取不到：
Mamanl抽象类实现Animal接口，在Animal接口上标记的注解，Mammal获取不到：
Rose类继承Flower抽象类，在Flower抽象类上标记的注解，如果注解是被@Inherited标记的，都可以获取到：@org.springmorning.demo.javabase.annotation.meta.Abbreviation(value=Flr) @org.springmorning.demo.javabase.annotation.meta.Name(value=Flower) 
Roxellanae类继承Monkey类，在Monkey抽象类上标记的注解，如果注解是被@Inherited标记的，都可以获取到；如果被@Inherited标记的注解父类和子类重复标记，则返回子类的注解：
@org.springmorning.demo.javabase.annotation.meta.Abbreviation(value=Mky) 
@org.springmorning.demo.javabase.annotation.meta.Name(value=Roxellanae) 
通过运行结果我们可以得出如下三点结论：

没有被@Inherited注解标记的注解，例如上例中的@UpperCaseName注解，就不具有继承特性，在子类中获取不到父类的注解；
@Inherited注解继承概念跟我们理解的面向对象继承概念不一样，它只作用于子类与父类之间的继承，像上例的Rose类就从Flower父类中继承了@Abbreviation和@Name注解；
对于接口之间的继承和类与接口之间的实现，这两种继承关系不起作用，像上例中Plant接口继承Organism接口、Mamanl类实现Animal接口，就没能继承@Abbreviation和@Name注解；
@Inherited注解标记的注解，在使用时，如果父类和子类都使用的注解是同一个，那么子类的注解会覆盖父类的注解，如上例中Roxellanae类用@Name注解标记了，Monkey类也用@Name注解
标记了，那么Roxellanae类注解，会覆盖Monkey的@Name注解。
*/